import { Repository, FindConditions, FindOneOptions, ObjectID, FindManyOptions, DeepPartial } from "typeorm";
import { ApiException } from "../../CoreModule/exception/api.exception";
import { ApiErrorCode } from "../enums/api-error-code";
import { HttpStatus } from "@nestjs/common";
import { QueryDeepPartialEntity } from "typeorm/query-builder/QueryDeepPartialEntity";

/**
 * @desc 抽象CURD操作基础服务
 * @author gebeibei
 * @date   2019/07/23
 */
export abstract class BasicService<Entity> {
    constructor(private readonly _model: Repository<Entity>) {}

    /**
     * @func  findAll 获取制定条件全部数据
     * @param { P in Entity[] } condition
     * @param { * } options
     * @param {
     *          select?: (keyof Entity)[],
     *          where?: FindConditions<Entity>[] | FindConditions<Entity> | ObjectLiteral | string ,
     *          relations?: string[],
     *          join?:  JoinOptions,
     *          order?: { [ P in keyof Entity]?:"ASC" | "DESC" | 1 | -1 },
     *          lock?: { mode:"optimistic", version: number | Date,} | { mode:"pessimistic_read" | "pessimistic_write" | "dirty_read" },
     *          cache?: boolean | number | { id:any, milliseconds:number },
     *          loadEagerRelations?: boolean,
     *          skip?:number,
     *          take?:number,         
     *         }
     * @param  { P inkeyof Entity }
     * @author gebeibei
     * @date   2019/07/23
     */
    async findAll (
        options?:FindManyOptions<Entity> | FindConditions<Entity>
    ):Promise<Entity[]>{
        try {
            return await this._model.find(options);
        }catch(err){
            console.log(err);
            throw new ApiException("数据库错误",ApiErrorCode.SERVER_ERROR,HttpStatus.INTERNAL_SERVER_ERROR)
        };
    }

    /**
     * @desc   带分页结构数据
     * @param  { options }
     * @param  { options.order?:{ [ P in keyof Entity]?:"ASC" | "DESC" | 1 | -1 }, }
     * @param  { options.pageNumber:number }
     * @param  { options.pageSize:number }
     * @param  { options.condition:FindConditions<Entity> }
     * @author gebeibei
     * @date   2019/07/23
     */
    async paginator (options?:any):Promise<object>{
        try {
            let findOptions = {
                order:options.order,
                where:options.condition,
                skip:(options.pageNumber - 1) * options.pageSize,
                take:options.pageSize
            }
            const result:[Entity[],number] = await this._model.findAndCount(findOptions);
            return {list:result[0],total:result[1]};
        }catch(err){
            console.log(err);
            throw new ApiException("数据库错误",ApiErrorCode.SERVER_ERROR,HttpStatus.INTERNAL_SERVER_ERROR)
        };
    }

     /**
     * @func   findOne 
     * @desc   获取指定条件的一个数据
     * @author gebeibei
     * @date   2019/07/23
     */
    async findOne (options?:FindOneOptions<Entity>):Promise<Entity>{
        try {
            return await this._model.findOne(options);
        }catch(err){
            console.log(err);
            throw new ApiException("数据库错误",ApiErrorCode.SERVER_ERROR,HttpStatus.INTERNAL_SERVER_ERROR)
        };
    }

    /**
     * @func   count 
     * @desc   获取指定条件的数据个数
     * @author gebeibei
     * @date   2019/07/23
     */
    async count (options?:FindManyOptions<Entity>):Promise<number>{
        try {
            return await this._model.count(options);
        }catch(err){
            console.log(err);
            throw new ApiException("数据库错误",ApiErrorCode.SERVER_ERROR,HttpStatus.INTERNAL_SERVER_ERROR)
        };
    }

    /**
     * @func   create 
     * @desc   创建数据
     * @author gebeibei
     * @date   2019/07/23
     */
    async create (entityLike?:DeepPartial<Entity>):Promise<Entity>{
        try {
            return await this._model.save(entityLike);
        }catch(err){
            console.log(err);
            throw new ApiException("数据库错误",ApiErrorCode.SERVER_ERROR,HttpStatus.INTERNAL_SERVER_ERROR)
        };
    }

    /**
     * @func   delete 
     * @desc   删除数据
     * @author gebeibei
     * @date   2019/07/23
     */
    async delete (
        criteria: string | string[] | number | number[] | Date | Date[] | ObjectID | ObjectID[] | FindConditions<Entity>
    ):Promise<string>{
        try {
            const result = await this._model.delete(criteria);
            return result.raw.affectedRows ? "删除成功" : "删除失败";
        }catch(err){
            console.log(err);
            throw new ApiException("数据库错误",ApiErrorCode.SERVER_ERROR,HttpStatus.INTERNAL_SERVER_ERROR)
        };
    }  

    /**
     * @func   update 
     * @desc   更新数据
     * @author gebeibei
     * @date   2019/07/23
     */
    async update (
        criteria: string | string[] | number | number[] | Date | Date[] | ObjectID | ObjectID[] | FindConditions<Entity>
    ):Promise<string>{
        try {
            const result = await this._model.update(criteria);
            return result.raw.affectedRows ? "更新成功" : "更新失败";
        }catch(err){
            console.log(err);
            throw new ApiException("数据库错误",ApiErrorCode.SERVER_ERROR,HttpStatus.INTERNAL_SERVER_ERROR)
        };
    }            
}